package handler

import (
	"context"
	"encoding/json"
	_ "github.com/astaxie/beego/cache/redis"
	"github.com/astaxie/beego/logs"
	"github.com/astaxie/beego/orm"
	_ "github.com/garyburd/redigo/redis"
	_ "github.com/gomodule/redigo/redis"
	"github.com/micro/go-micro/util/log"
	"ihome/models"
	getArea "ihome/proto/getArea"
	"ihome/utils"
	"time"
)

type GetArea struct{}

// Call is a single request handler called via client.Call or the generated client code
func (e *GetArea) GetAreas(ctx context.Context, req *getArea.Request, rsp *getArea.Response) error {
	logs.Info("请求地区信息 GetAreas api/v1.0/areas")

	rsp.Code = utils.RecodeOk
	rsp.Msg = utils.RecodeText(rsp.Code)

	bm, err := utils.NewCache()
	if err != nil {
		logs.Info("redis连接失败", err)
		rsp.Code = utils.RecodeDberr
		rsp.Msg = utils.RecodeText(rsp.Code)
		return nil
	}

	areasValue := bm.Get("area_info")

	if areasValue != nil {
		logs.Info("获取到地址信息缓存")
		var areasMap []map[string]interface{}
		json.Unmarshal(areasValue.([]byte), &areasMap)
		for _, value := range areasMap {
			tmp := getArea.Response_Areas{
				Aid:   int32(value["aid"].(float64)),
				Aname: value["aname"].(string),
			}
			rsp.Data = append(rsp.Data, &tmp)
		}
		return nil
	}

	o := orm.NewOrm()
	qs := o.QueryTable("area")

	var areas []models.Area
	num, err := qs.All(&areas)
	if err != nil {
		logs.Info("数据库查询失败", err)
		rsp.Code = utils.RecodeNodata
		rsp.Msg = utils.RecodeText(rsp.Code)
		return nil
	}
	if num == 0 {
		logs.Info("数据库没有数据", num)
		rsp.Code = utils.RecodeNodata
		rsp.Msg = utils.RecodeText(rsp.Code)
		return nil
	}

	areaJson, _ := json.Marshal(areas)
	err = bm.Put("area_info", areaJson, time.Second*3600)
	if err != nil {
		logs.Info("数据缓存失败", num)
		rsp.Code = utils.RecodeDataerr
		rsp.Msg = utils.RecodeText(rsp.Code)
		return nil
	}

	for _, area := range areas {
		tmp := getArea.Response_Areas{
			Aid:   int32(area.Id),
			Aname: area.Name,
		}
		rsp.Data = append(rsp.Data, &tmp)
	}

	return nil
}

// Stream is a server side stream handler called via client.Stream or the generated client code
func (e *GetArea) Stream(ctx context.Context, req *getArea.StreamingRequest, stream getArea.GetArea_StreamStream) error {
	log.Logf("Received GetArea.Stream request with count: %d", req.Count)

	for i := 0; i < int(req.Count); i++ {
		log.Logf("Responding: %d", i)
		if err := stream.Send(&getArea.StreamingResponse{
			Count: int64(i),
		}); err != nil {
			return err
		}
	}

	return nil
}

// PingPong is a bidirectional stream handler called via client.Stream or the generated client code
func (e *GetArea) PingPong(ctx context.Context, stream getArea.GetArea_PingPongStream) error {
	for {
		req, err := stream.Recv()
		if err != nil {
			return err
		}
		log.Logf("Got ping %v", req.Stroke)
		if err := stream.Send(&getArea.Pong{Stroke: req.Stroke}); err != nil {
			return err
		}
	}
}
